home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / das / passg.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  11KB  |  409 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  PASSG.C
  9.  *
  10.  *  Generate the code...
  11.  *
  12.  *  Note that mc->OpSize may be 0.  By this point, we take it to mean the
  13.  *  instruction is unsized or single-sized.  This really only effects the
  14.  *  immediate addressing mode.
  15.  */
  16.  
  17. #include "defs.h"
  18.  
  19. Prototype void    PassG(void);
  20. Prototype long    GenerateInstruction(MachCtx *);
  21. Prototype long    RegMaskForInst(short, long);
  22. Prototype long    GenerateEA(short, MachCtx *, OpCod *, EffAddr *, uword *);
  23.  
  24. void
  25. PassG()
  26. {
  27.     MachCtx **pmc;
  28.     MachCtx *mc;
  29.     OpCod   *oc;
  30.     long i;
  31.     long addr = 0;
  32.  
  33.     pmc = MBase;
  34.     for (i = 0; i < MLines; ++i) {
  35.     mc = *pmc++;
  36.     LineNo = mc->LineNo;
  37.     if (mc->Label && mc->Label->l_Offset != mc->m_Addr)
  38.         cerror(EERROR_LABEL_ADDR_MISMATCH, mc->Label->Name, mc->Label->l_Offset, mc->m_Addr);
  39.     if ((oc = mc->OpCode) == NULL)
  40.         continue;
  41.     if (mc->m_Addr != addr)
  42.         cerror(EERROR_ADDR_MISMATCH, mc->m_Addr, addr);
  43.     if (oc->Id < 0) {
  44.         addr = ExecOpCodeG(mc, addr);
  45.         continue;
  46.     }
  47.     addr += GenerateInstruction(mc);
  48.     }
  49. }
  50.  
  51. static uword Code[16];
  52.  
  53. long
  54. GenerateInstruction(mc)
  55. MachCtx *mc;
  56. {
  57.     OpCod *oc = mc->OpCode;
  58.     uword opcode = oc->Template;
  59.     uword numWords = 1;
  60.  
  61.     /*
  62.      *    Step one, the instruction word itself
  63.      */
  64.  
  65.     {
  66.     short spec;
  67.  
  68.     if (oc->B_Siz >= 0) {   /*  bits in inst word for size  */
  69.         if (mc->OpSize == 2)
  70.         opcode |= 1 << oc->B_Siz;
  71.         if (mc->OpSize == 4)
  72.         opcode |= 2 << oc->B_Siz;
  73.     }
  74.     if (oc->B_Rs >= 0) {    /*  source register */
  75.         if ((spec = RegCode[(short)mc->Oper1.Mode1]) >= 0)
  76.         opcode |= spec << oc->B_Rs;
  77.         else
  78.         opcode |= (mc->Oper1.Reg1 & 7) << oc->B_Rs;
  79.     }
  80.     if (oc->B_EAs >= 0)     /*  source eff addr */
  81.         opcode |= EACode[(short)mc->Oper1.Mode1] << oc->B_EAs;
  82.  
  83.     if (oc->B_Rd >= 0) {    /*  dest register   */
  84.         if ((spec = RegCode[(short)mc->Oper2.Mode1]) >= 0)
  85.         opcode |= spec << oc->B_Rd;
  86.         else
  87.         opcode |= (mc->Oper2.Reg1 & 7) << oc->B_Rd;
  88.     } else if (oc->DModes & AF_MULDREGS) {
  89.         Code[1] = ToMsbOrderShort(((mc->Oper2.Reg1 & 7) << 12) | 0x0800);
  90.         numWords = 2;
  91.     } else if (oc->DModes & AF_MULDREGU) {
  92.         Code[1] = ToMsbOrderShort(((mc->Oper2.Reg1 & 7) << 12) | 0x0000);
  93.         numWords = 2;
  94.     }
  95.     if (oc->B_EAd >= 0)     /*  dest eff addr   */
  96.         opcode |= EACode[(short)mc->Oper2.Mode1] << oc->B_EAd;
  97.  
  98.     /*
  99.      *  MOVEM instruction special case, mask always comes next
  100.      */
  101.  
  102.     if (oc->Id == OpMOVEM)
  103.         numWords = 2;
  104.  
  105.     /*
  106.      *  note, in-instruction immediate data further on in routine.    Also
  107.      *  absolute word/long determined below.
  108.      */
  109.     }
  110.  
  111.     Code[0] = ToMsbOrderShort(opcode);
  112.  
  113.     numWords = GenerateEA(numWords, mc, oc, &mc->Oper1, Code + numWords);
  114.     numWords = GenerateEA(numWords, mc, oc, &mc->Oper2, Code + numWords);
  115.  
  116.     dbprintf(0, ("line %ld bytes %d operModes %d %d\n", LineNo, numWords * 2, mc->Oper1.Mode1, mc->Oper2.Mode1));
  117.  
  118.     DumpSectionData(mc->Sect, Code, numWords*2);
  119.     return(numWords*2);
  120. }
  121.  
  122. long
  123. RegMaskForInst(short mode, long mask)
  124. {
  125.     long rvs = 0;
  126.     short i;
  127.  
  128.     if (mode != AB_MMIND)
  129.     return(mask);
  130.  
  131.     for (i = 0; i < 16; ++i) {
  132.     if (mask & (1 << i))
  133.         rvs |= 1 << (15-i);
  134.     }
  135.     return(rvs);
  136. }
  137.  
  138. /*
  139.  *  returns number of extension words added
  140.  */
  141.  
  142. long
  143. GenerateEA(short numWords, MachCtx *mc, OpCod *oc, EffAddr *ea, uword *ext)
  144. {
  145.     int numBytes = numWords * 2;
  146.  
  147.     /*
  148.      *    relocation
  149.      */
  150.  
  151.     {
  152.     Label *lab;
  153.  
  154.     /*
  155.      *  fixup for local labels, base displacement
  156.      */
  157.  
  158.     if ((lab = ea->Label2) && lab->l_Type == LT_LOC) {
  159.         ea->Offset2 += lab->l_Offset;
  160.  
  161.         switch(ea->Mode1) {
  162.         case AB_OFFIDXPC:
  163.         case AB_OFFPC:
  164.         case AB_BBRANCH:
  165.         case AB_WBRANCH:
  166.         if (lab->Sect == CurSection) {
  167.             ea->Offset2 -= (mc->m_Addr + numWords*2);
  168.             ea->Label2 = NULL;
  169.         }
  170.         break;
  171.         }
  172.     }
  173.  
  174.     /*
  175.      *  fixup for local labels, offset or index value (but not outer
  176.      *  displacement since it is not PC relative)
  177.      */
  178.  
  179.     if ((lab = ea->Label1) && lab->l_Type == LT_LOC) {
  180.         ea->Offset1 += lab->l_Offset;
  181.  
  182.         switch(ea->Mode1) {
  183.         case AB_OFFIDXPC:
  184.         if ((ea->ExtWord & EXTF_ODMASK) == EXTF_ODWORD || (ea->ExtWord & EXTF_ODMASK) == EXTF_ODLONG) {
  185.             break;
  186.         }
  187.         case AB_OFFPC:
  188.         case AB_BBRANCH:
  189.         case AB_WBRANCH:
  190.         if (lab->Sect == CurSection) {
  191.             ea->Offset1 -= (mc->m_Addr + numWords*2);
  192.             ea->Label1 = NULL;
  193.         }
  194.         }
  195.     }
  196.  
  197.     }
  198.  
  199.     /*
  200.      *    mode and extension words
  201.      */
  202.  
  203.     switch(ea->Mode1) {
  204.     case 0:
  205.     case AB_DN:
  206.     case AB_AN:
  207.     case AB_INDAN:
  208.     case AB_INDPP:
  209.     case AB_MMIND:
  210.     break;
  211.     case AB_OFFAN:
  212.     if (ea->Label1)
  213.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 2, RELOC_DATAREL);
  214.     ++numWords;
  215.     ext[0] = ToMsbOrderShort(ea->Offset1);
  216.     if (ea->Offset1 < -32768 || ea->Offset1 > 32767)
  217.         cerror(EERROR_WORD_OFFSET, ea->Offset1);
  218.     break;
  219.     case AB_OFFIDX:
  220.     case AB_OFFIDXPC:
  221.     if (ea->ExtWord & EXTF_FULL) {
  222.         int i = 1;
  223.  
  224.         switch(ea->ExtWord & EXTF_BDMASK) {
  225.         case EXTF_BDWORD:
  226.         if (ea->Label2) {
  227.             long reloc_type = (ea->Mode1 == AB_OFFIDXPC) ? RELOC_PCREL : ((ea->ISize & ISF_BDDREL) ? RELOC_DATAREL : 0);
  228.  
  229.             HandleInstReloc(mc->Sect, ea->Label2, mc->m_Addr + numBytes + 2, 2, reloc_type);
  230.             /*
  231.              *    address will be relocated relative to label instead
  232.              *    of to extension word, must compensate
  233.              */
  234.             ea->Offset2 += 2;
  235.         }
  236.         ext[i++] = ToMsbOrderShort(ea->Offset2);
  237.         break;
  238.         case EXTF_BDLONG:
  239.         if (ea->Label2) {
  240.             long reloc_type = (ea->Mode1 == AB_OFFIDXPC) ? RELOC_PCREL : ((ea->ISize & ISF_BDDREL) ? RELOC_DATAREL : 0);
  241.  
  242.             HandleInstReloc(mc->Sect, ea->Label2, mc->m_Addr + numBytes + 2, 4, reloc_type);
  243.             ea->Offset2 += 2;
  244.         }
  245.         ext[i++] = ToMsbOrderShort(ea->Offset2 >> 16);
  246.         ext[i++] = ToMsbOrderShort(ea->Offset2);
  247.         break;
  248.         }
  249.         switch(ea->ExtWord & EXTF_ODMASK) {
  250.         case EXTF_ODWORD:
  251.         if (ea->Label1) {
  252.             long reloc_type = (ea->ISize & ISF_ODDREL) ? RELOC_DATAREL : 0;
  253.             HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes + i * 2, 2, reloc_type);
  254.         }
  255.         ext[i++] = ToMsbOrderShort(ea->Offset1);
  256.         break;
  257.         case EXTF_ODLONG:
  258.         if (ea->Label1) {
  259.             long reloc_type = (ea->ISize & ISF_ODDREL) ? RELOC_DATAREL : 0;
  260.             HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes + i * 2, 4, reloc_type);
  261.         }
  262.         ext[i++] = ToMsbOrderShort(ea->Offset1 >> 16);
  263.         ext[i++] = ToMsbOrderShort(ea->Offset1);
  264.         break;
  265.         }
  266.         numWords += i;
  267.         ext[0] = ToMsbOrderShort(ea->ExtWord);
  268.     } else {
  269.         if (ea->Label1)
  270.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes + 1, 1, 0);
  271.         if (ea->Offset1 < -128 || ea->Offset1 > 127)
  272.         cerror(EERROR_BYTE_OFFSET, ea->Offset1);
  273.         ext[0] = ToMsbOrderShort(ea->ExtWord | (ea->Offset1 & 0xFF));
  274.         ++numWords;
  275.     }
  276.     break;
  277.     case AB_ABSW:
  278.     if (ea->Label1)
  279.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 2, 0);
  280.     ++numWords;
  281.     ext[0] = ToMsbOrderShort(ea->Offset1);
  282.     break;
  283.     case AB_ABSL:
  284.     if (ea->Label1)
  285.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 4, 0);
  286.     numWords += 2;
  287.     ext[0] = ToMsbOrderShort(ea->Offset1 >> 16);
  288.     ext[1] = ToMsbOrderShort(ea->Offset1);
  289.     break;
  290.     case AB_OFFPC:
  291.     if (ea->Label1)
  292.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 2, RELOC_PCREL);
  293.     ++numWords;
  294.     ext[0] = ToMsbOrderShort(ea->Offset1);
  295.     if (ea->Offset1 < -32768 || ea->Offset1 > 32767)
  296.         cerror(EERROR_WORD_OFFSET, ea->Offset1);
  297.     break;
  298.     case AB_IMM:
  299.     switch(oc->Special) {
  300.     case IMM07:
  301.         if (ea->Label1)
  302.         cerror(EERROR_BAD_RELOC);
  303.         Code[0] |= ToMsbOrderShort((ea->Offset1 & 7) << 9);
  304.         if (ea->Offset1 < 0 || ea->Offset1 > 7)
  305.         cerror(EERROR_7_OFFSET, ea->Offset1);
  306.         break;
  307.     case IMM18:
  308.         if (ea->Label1)
  309.         cerror(EERROR_BAD_RELOC);
  310.         Code[0] |= ToMsbOrderShort((ea->Offset1 & 7) << 9);
  311.         if (ea->Offset1 < 1 || ea->Offset1 > 8)
  312.         cerror(EERROR_8_OFFSET, ea->Offset1);
  313.         break;
  314.     case IMM0F:
  315.         if (ea->Label1)
  316.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + 1, 1, 0);
  317.         Code[0] |= ToMsbOrderShort(ea->Offset1 & 15);
  318.         if (ea->Offset1 < 0 || ea->Offset1 > 15)
  319.         cerror(EERROR_15_OFFSET, ea->Offset1);
  320.         break;
  321.     case IMM256:
  322.         if (ea->Label1)
  323.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + 1, 1, 0);
  324.         Code[0] |= ToMsbOrderShort(ea->Offset1 & 0xFF);
  325.         if (ea->Offset1 < -128 || ea->Offset1 > 127)
  326.         cerror(EERROR_BYTE_OFFSET, ea->Offset1);
  327.         break;
  328.     case IMMB:
  329.         if (ea->Label1)
  330.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes + 1, 1, 0);
  331.         ext[0] = ToMsbOrderShort(ea->Offset1 & 0xFF);
  332.         ++numWords;
  333.         break;
  334.     default:
  335.         if (mc->OpSize == 0) {
  336.         if (oc->Sizes & S_B)
  337.             mc->OpSize = 1;
  338.         if (oc->Sizes & S_W)
  339.             mc->OpSize = 2;
  340.         if (oc->Sizes & S_L)
  341.             mc->OpSize = 4;
  342.         }
  343.  
  344.         switch(mc->OpSize) {
  345.         case 1:
  346.         if (ea->Label1)
  347.             HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes + 1, 1, 0);
  348.         ext[0] = ToMsbOrderShort(ea->Offset1 & 0xFF);
  349.         ++numWords;
  350.         break;
  351.         case 2:
  352.         if (ea->Label1)
  353.             HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 2, RELOC_PCREL);
  354.         ext[0] = ToMsbOrderShort(ea->Offset1);
  355.         ++numWords;
  356.         break;
  357.         case 4:
  358.         if (ea->Label1)
  359.             HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + numBytes, 4, 0);
  360.         ext[0] = ToMsbOrderShort(ea->Offset1 >> 16);
  361.         ext[1] = ToMsbOrderShort(ea->Offset1);
  362.         numWords += 2;
  363.         break;
  364.         }
  365.     }
  366.     break;
  367.     case AB_REGS:
  368.     Code[1] = ToMsbOrderShort(RegMaskForInst(mc->Oper2.Mode1, ea->ExtWord));
  369.     break;
  370.     case AB_BBRANCH:
  371.     /*
  372.      *  since byte branches are relative to the base of the
  373.      *  instruction word, NOT the address of the offset, we
  374.      *  have to compensate -1
  375.      */
  376.  
  377.     if (ea->Label1) {
  378.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + 1, 1, 0);
  379.         Code[0] |= ToMsbOrderShort((ea->Offset1 - 1) & 0xFF);
  380.     } else {
  381.         Code[0] |= ToMsbOrderShort((ea->Offset1) & 0xFF);
  382.     }
  383.  
  384.     if (ea->Label1 == NULL && ea->Offset1 == 0)
  385.         cerror(EERROR_SHORT_BRANCH);
  386.     if (ea->Offset1 < -128 || ea->Offset1 > 127)
  387.         cerror(EERROR, "byte branch offset too large");
  388.     break;
  389.     case AB_WBRANCH:
  390.     if (ea->Label1)
  391.         HandleInstReloc(mc->Sect, ea->Label1, mc->m_Addr + 2, 2, RELOC_PCREL);
  392.  
  393.     ++numWords;
  394.     ext[0] = ToMsbOrderShort(ea->Offset1);
  395.     if (ea->Offset1 < -32768 || ea->Offset1 > 32767)
  396.         cerror(EERROR_WORD_OFFSET, ea->Offset1);
  397.     break;
  398.     case AB_CCR:
  399.     case AB_SR:
  400.     case AB_USP:
  401.     break;
  402.     default:
  403.     cerror(ESOFT_BAD_SRCAB, ea->Mode1);
  404.     break;
  405.     }
  406.     return(numWords);
  407. }
  408.  
  409.